package kvraft

import (
	uuid `github.com/satori/go.uuid`
)

type ServerError string

var uuidFactory, _ = uuid.NewV4()

const (
	OK             ServerError = ""
	ErrNoKey       ServerError = "ErrNoKey"
	ErrWrongLeader ServerError = "ErrWrongLeader"
	ErrHasCommit   ServerError = "ErrHasCommit"
	ErrKilled      ServerError = "Killed"
	ErrNoOp        ServerError = "ErrNoOp"
)

type ClientGeneralArgs struct {
	ClientId  string
	RequestId uint64
}

type ClientGeneralReply struct {
	Err ServerError
}

func (c *ClientGeneralReply) Error() ServerError {
	return c.Err
}

type generalReply struct {
	Err   ServerError
	Value string
}

// Put or Append
type PutAppendArgs struct {
	Key   string
	Value string
	Op    string // "Put" or "Append"
	ClientGeneralArgs
	// You'll have to add definitions here.
	// Field names must start with capital letters,
	// otherwise RPC will break.
}

type PutAppendReply struct {
	Value string
	ClientGeneralReply
}

type GetArgs struct {
	Key string
	ClientGeneralArgs
	// You'll have to add definitions here.
}

type GetReply struct {
	Value string
	ClientGeneralReply
}

type StateArgs struct {
}

type StateReply struct {
	IsLeader bool
	Term     int
	Index    int
	Err      ServerError
}

type Op struct {
	// Your definitions here.
	// Field names must start with capital letters,
	// otherwise RPC will break.
	Name      string
	Key       string
	Value     string
	ClientId  string
	RequestId uint64
	UUID      string
}

func (op *Op) Hash() string {
	return op.UUID
}

func (op *Op) getClientId() string {
	return op.ClientId
}

func (op *Op) getRequestId() uint64 {
	return op.RequestId
}

func GetArgs2Op(args *GetArgs) *Op {
	return &Op{
		Name:      "get",
		Key:       args.Key,
		Value:     "",
		ClientId:  args.ClientId,
		RequestId: args.RequestId,
		UUID:      GetUUID(),
	}
}

func PutAppendArgs2Op(args *PutAppendArgs) *Op {
	return &Op{
		Name:      args.Op,
		Key:       args.Key,
		Value:     args.Value,
		ClientId:  args.ClientId,
		RequestId: args.RequestId,
		UUID:      GetUUID(),
	}
}
